import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
  FlatList,
  LayoutChangeEvent,
  StyleSheet,
  useWindowDimensions,
  View,
  ViewStyle,
} from "react-native";
// 数据项接口
interface Item {
  [key: string]: any;
  id: string | number;
  title?: string;
  height?: number; // 可选：预计算高度
  originalWidth?: number; // 可选：原始宽度
  originalHeight?: number; // 可选：原始高度
}
// 布局后的数据项
interface LayoutItem extends Item {
  x: number;
  y: number;
  width: number;
  actualHeight?: number;
}
// 组件属性
interface WaterfallListProps {
  data: Item[];
  numColumns?: number;
  columnGap?: number;
  rowGap?: number;
  paddingLeft?: number;
  paddingRight?: number;
  onLoadMore?: () => void;
  refreshing?: boolean;
  onRefresh?: () => void;
  renderItem: (item: any) => React.ReactElement;
  renderFooter?: (item: any) => React.ReactElement;
  renderHeader?: (item: any) => React.ReactElement;
  style?: ViewStyle;
}
const WaterfallList: React.FC<WaterfallListProps> = ({
  data = [],
  numColumns = 2,
  columnGap = 8,
  rowGap = 8,
  paddingLeft = 8,
  paddingRight = 8,
  onLoadMore,
  refreshing = false,
  onRefresh,
  renderItem,
  renderFooter,
  renderHeader,
  style,
}) => {
  const { width: windowWidth } = useWindowDimensions();
  const [layoutData, setLayoutData] = useState<LayoutItem[]>([]);
  const [measuredItems, setMeasuredItems] = useState<Record<string, number>>(
    {}
  );
  // 计算列宽
  const contentWidth = useMemo(
    () =>
      windowWidth - columnGap * (numColumns - 1) - paddingLeft - paddingRight,
    [windowWidth, numColumns, columnGap, paddingLeft, paddingRight]
  );
  const columnWidth = useMemo(
    () => contentWidth / numColumns,
    [contentWidth, numColumns]
  );
  // 布局算法
  useEffect(() => {
    const layoutItems = calculateLayout(
      data,
      numColumns,
      columnWidth,
      rowGap,
      measuredItems
    );
    setLayoutData(layoutItems);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [data, numColumns, columnWidth, rowGap, measuredItems]);
  // 计算瀑布流布局
  const calculateLayout = useCallback(
    (
      items: Item[],
      numColumns: number,
      columnWidth: number,
      rowGap: number,
      measuredHeights: Record<string, number>
    ): LayoutItem[] => {
      // 初始化列高度记录
      const columnHeights: number[] = Array(numColumns).fill(0);
      return items.map((item) => {
        // 确定当前高度（测量值 > 预计算值 > 基于原始尺寸计算 > 默认值）
        const height =
          measuredHeights[item.id] ||
          item.height ||
          (item.originalWidth && item.originalHeight
            ? (columnWidth / item.originalWidth) * item.originalHeight
            : 200);
        // 找到当前最短的列
        const shortestColumnIndex = columnHeights.reduce(
          (minIndex, height, index) =>
            height < columnHeights[minIndex] ? index : minIndex,
          0
        );
        // 计算项目位置
        const x = shortestColumnIndex * (columnWidth + columnGap);
        const y = columnHeights[shortestColumnIndex];
        // 更新列高度
        columnHeights[shortestColumnIndex] = y + height + rowGap;
        return {
          ...item,
          x,
          y,
          width: columnWidth,
          actualHeight: height,
        };
      });
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    []
  );
  // 处理项目布局变化
  const handleLayout = useCallback(
    (itemId: string | number, event: LayoutChangeEvent) => {
      const { height } = event.nativeEvent.layout;
      // 仅在高度变化时更新
      if (height !== measuredItems[itemId]) {
        setMeasuredItems((prev) => ({ ...prev, [itemId]: height }));
      }
    },
    [measuredItems]
  );
  // 获取列表总高度
  const getListHeight = useCallback(() => {
    if (layoutData.length === 0) return 0;
    // 找到所有列中的最大高度
    const columnHeights: number[] = Array(numColumns).fill(0);
    layoutData.forEach((item) => {
      const columnIndex = Math.floor(item.x / (columnWidth + columnGap));
      const itemHeight = item.actualHeight || 200;
      columnHeights[columnIndex] = Math.max(
        columnHeights[columnIndex],
        item.y + itemHeight
      );
    });
    return Math.max(...columnHeights);
  }, [layoutData, numColumns, columnWidth, columnGap]);
  // 渲染项目
  const renderWaterfallItem = useCallback(
    ({ item }: { item: LayoutItem }) => (
      <View
        key={item.id}
        style={{
          position: "absolute",
          left: item.x,
          top: item.y,
          width: item.width,
        }}
        onLayout={(event) => handleLayout(item.id, event)}
      >
        {renderItem(item)}
      </View>
    ),
    [handleLayout, renderItem]
  );
  // 渲染底部加载更多
  const Footer = useCallback(
    ({ item }: { item: LayoutItem }) => {
      return (
        <View
          style={[
            styles.footerBox,
            {
              position: "absolute",
              top: getListHeight(),
            },
          ]}
        >
          {renderFooter && renderFooter(item)}
        </View>
      );
    },
    [renderFooter, getListHeight]
  );
  return (
    <>
      <FlatList
        style={[style]}
        data={layoutData}
        renderItem={renderWaterfallItem}
        keyExtractor={(item) => item.id.toString()}
        contentContainerStyle={{
          minHeight: "100%",
          width: windowWidth,
          height: getListHeight() + 80,
        }}
        showsVerticalScrollIndicator={false}
        onEndReached={onLoadMore}
        onEndReachedThreshold={0.1}
        ListFooterComponent={Footer}
        ListHeaderComponent={renderHeader}
        refreshing={refreshing}
        onRefresh={onRefresh}
      />
    </>
  );
};
const styles = StyleSheet.create({
  footerBox: {
    width: "100%",
    alignItems: "center",
    justifyContent: "center",
  },
});
export default WaterfallList;
